package com.sutong.platform.service.impl;

import cn.hutool.bloomfilter.BitMapBloomFilter;
import cn.hutool.bloomfilter.BloomFilterUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.hash.MurmurHash;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sutong.common.result.ErrorCode;
import com.sutong.platform.exception.BusinessException;
import com.sutong.platform.mapper.ShortLinkMapper;
import com.sutong.platform.model.entity.ShortLink;
import com.sutong.platform.model.vo.ShortLinkVo;
import com.sutong.platform.service.ShortLinkService;
import com.sutong.platform.utils.DecimalToBase64Converter;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author sutong
 * @description 短链表Service实现
 */
@Service
public class ShortLinkServiceImpl extends ServiceImpl<ShortLinkMapper, ShortLink>
        implements ShortLinkService {

    private final BitMapBloomFilter bloomFilter = BloomFilterUtil.createBitMap(64);
    private final String HOST = "http://localhost:8080/api/sl/";

    /**
     * 生成短链
     *
     * @param originalLongUrl
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShortLinkVo generateShortUrl(String originalLongUrl) {
        if (StrUtil.isBlank(originalLongUrl)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        StringBuilder longUrl = new StringBuilder(originalLongUrl);
        String shortUrlPath = getShortUrl(longUrl.toString());
        while (bloomFilter.contains(shortUrlPath)) {
            longUrl.append(RandomUtil.randomString(5));
            shortUrlPath = getShortUrl(longUrl.toString());
        }
        ShortLink shortLink = new ShortLink();
        shortLink.setLongUrl(originalLongUrl);
        shortLink.setShortUrl(shortUrlPath);
        bloomFilter.add(shortUrlPath);
        save(shortLink);

        String shortUrl = HOST + shortUrlPath;
        byte[] bytes = QrCodeUtil.generatePng(shortUrl, 200, 200);
        String shortLinkQrCode = Base64.encode(bytes);
        ShortLinkVo shortLinkVo = new ShortLinkVo();
        shortLinkVo.setShortUrlQrCode(shortLinkQrCode);
        shortLinkVo.setShortUrl(shortUrl);
        return shortLinkVo;
    }

    /**
     * 获取长链
     *
     * @param shortUrl
     * @return
     */
    @Override
    public String getLongUrl(String shortUrl) {
        if (StrUtil.isBlank(shortUrl)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        ShortLink shortLink = lambdaQuery().eq(ShortLink::getShortUrl, shortUrl).one();
        return ObjectUtil.isNull(shortLink) ? null : shortLink.getLongUrl();
    }

    /**
     * 访问次数加一
     *
     * @param shortUrl
     */
    @Async
    @Override
    public void visitCountPlus(String shortUrl) {
        lambdaUpdate().setSql("visitCount = visitCount + 1").eq(ShortLink::getShortUrl, shortUrl).update();
    }

    /**
     * 通过MurmurHash算法生成hash值，然后转化为64进制，减少长度
     */
    private String getShortUrl(String longUrl) {
        long hash64 = MurmurHash.hash64(longUrl);
        return DecimalToBase64Converter.decimalToBase64(Math.abs(hash64));
    }
}




